package com.ellecity06.common.paging3.quick

import androidx.paging.*
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow

/**
 * @author ellecity06
 * @time 2023/4/22 17:31
 * @des
 */
class QuickPagingSource<V : Any>(
    private val scope: CoroutineScope,
    private val pageSize: Int = 20,
    private val initialLoadSize: Int = pageSize,
    private val prefetchDistance: Int = pageSize,
    private val maxSize: Int = PagingConfig.MAX_SIZE_UNBOUNDED,
    private val enablePlaceholders: Boolean = false,
    private val initialKey: Int? = null,
    private val pagingSource: () -> PagingSource<Int, V>? = { null },
    private val loadData: suspend (PagingSource.LoadParams<Int>) -> PagingSource.LoadResult<Int, V>? = { null }
) {


    fun getData(): Flow<PagingData<V>> {
        return Pager(
            PagingConfig(
                pageSize,
                initialLoadSize = initialLoadSize,
                prefetchDistance = prefetchDistance,
                maxSize = maxSize,
                enablePlaceholders = enablePlaceholders
            ),
            initialKey = initialKey
        ) {
            pagingSource() ?: object : PagingSource<Int, V>() {
                override suspend fun load(params: LoadParams<Int>): LoadResult<Int, V> {
                    return loadData(params) ?: throw IllegalArgumentException(
                        "one of pagingSource or loadData must not null"
                    )
                }

                override fun getRefreshKey(state: PagingState<Int, V>): Int? {
                    return state.anchorPosition?.let { anchorPosition ->
                        val anchorPage = state.closestPageToPosition(anchorPosition)
                        anchorPage?.prevKey?.plus(1) ?: anchorPage?.nextKey?.minus(1)
                    }
                }
            }
        }.flow.cachedIn(scope)
    }

    fun getScope() = scope
}